package cc.eddic.practice.spring.webapi;

import cc.eddic.practice.spring.domain.SubCategory;
import cc.eddic.practice.spring.dto.*;
import cc.eddic.practice.spring.repository.CategoryRepository;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.transaction.Transactional;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;

/*

1.
GETMapping("/{}")
PostMapping
DeleteMapping("/{}")

2.
public <?> add（参数）{
   val * = model.as() 创建要添加的对象
   repository.save(*) 添加
   }

public <返回值> get/delete(参数){
   findBy**(属性).orElseThrow() 根据传入的参数找对象
   }

 */

@Slf4j
@RestController
@RequestMapping("/api/categories")

public class CategoryRestController {

    private final CategoryRepository repository;

    public CategoryRestController(CategoryRepository repository){
        this.repository=repository;
    }

    @PostMapping
    public HttpEntity<?> add(@RequestBody final CategoryAddRequest model){
        val category=repository.save(model.as());//as()创建新的student对象
        return ResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(category.getId()).toUri()).build();
    }

    @GetMapping("/{id}")
    public HttpEntity<CategoryResponse> get(@PathVariable("id") final long id){
        if(log.isDebugEnabled()) log.debug("id = {}",id);
        val category = repository.findById(id).orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(CategoryResponse.from(category));
    }

    @DeleteMapping("/{id}")
    public HttpEntity<?> del(@PathVariable("id") final long id){
        repository.deleteById(id);
        return ResponseEntity.noContent().build();
    }

    @GetMapping
    public HttpEntity<List<CategoryResponse>> getAll(){
        val categorys=repository.findAll().stream().map(CategoryResponse::from).collect(Collectors.toList());
        return ResponseEntity.ok(categorys);
    }

    @Transactional
    @PostMapping("/{categoryID}/subcategories")
    public HttpEntity<?> add(@PathVariable("categoryID") Long categoryID, @RequestBody final SubCategoryAddRequest model){
        val category =repository.findById(categoryID).orElseThrow(NoSuchElementException::new);//根据add方法的输入参数确定 要插入的subcategory属于那个category
        val subCategory=model.as();//根据add方法的输入参数 创建subcategory的对象
        category.add(subCategory);//把subcategory添加到category存储的subcategory的列表中
        repository.save(category);//添加

        val id = category.getSubCategories().stream()
                .filter(x->x.getName().equals(model.getName()))
                .sorted(Comparator.comparing(SubCategory::getCreatedOn).reversed())
                .map(SubCategory::getId)
                .findFirst().orElse(-1L);
        if(log.isDebugEnabled()){
            log.debug("sub category id{}",subCategory.getId());
            log.debug("(filter) sub category id {}",id);
        }

        //返回添加后生成的网址
        return ResponseEntity.created(ServletUriComponentsBuilder.fromCurrentRequest().path("/{categoryID}/subcategorys/{subCategoryID}").buildAndExpand(category.getId(),subCategory.getId()).toUri()).build();
    }

    //?为什么不能返回subCategory列表
    @GetMapping("/{categoryID}/subcategories")
    public HttpEntity<?> get(@PathVariable("categoryID") Long categoryID){
        if(log.isDebugEnabled()) log.debug("categoryID={}",categoryID);
        val category=repository.findById(categoryID).orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(category.getSubCategories().stream().map(SubCategoryResponse::from).collect(Collectors.toList()));
    }

    @GetMapping("/{categoryID}/subcategories/{subCategoryID}")
    public HttpEntity<?> get(@PathVariable("categoryID") Long categoryID,@PathVariable("subCategoryID") Long subCategoryID){
        if(log.isDebugEnabled()) log.debug("categoryID={},subCategoryID={}",categoryID,subCategoryID);
        val category=repository.findById(categoryID).orElseThrow(NoSuchElementException::new);
        val subcategory=category.getSubCategories().stream().filter(subCategory -> subCategory.getId().equals(subCategoryID)).findFirst().orElseThrow(NoSuchElementException::new);
        return ResponseEntity.ok(SubCategoryResponse.from(subcategory));
    }
}
